package com.tian.arch.function.state

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout

/**
 * 拥有状态的页面
 */
class StatefulPage @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : FrameLayout(context, attrs, defStyleAttr), PageAbility {

    // 存储状态 和对应载入的布局
    private val statusView = mutableMapOf<PageStatus, View>()
    private var retryTask: (() -> Unit)? = null

    // 当前状态，只能获取
    var currentState = PageStatus.LOADING
        private set

    lateinit var config: PageStateConfig

    /**
     *  更新PageStateConfig
     *
     *  当如出错layout，loadingLayout这类配置信息发生改变时，"StatefulPage"组件应该只保留真正内容的显示
     */
    fun updateConfig(action: PageStateConfig.() -> Unit) {
        action(config)
        statusView
            .filter {
                it.key != PageStatus.CONTENT
            }.forEach {
                removeView(it.value)
            }
        statusView.clear()
    }

    /**
     * 设置重试
     */
    fun setRetryAction(retryTask: () -> Unit): StatefulPage {
        this.retryTask = retryTask
        return this
    }

    override fun showLoading() {
        innerShow(PageStatus.LOADING)
    }

    override fun showError(errorMsg: String?) {
        innerShow(PageStatus.ERROR)
    }

    override fun showEmpty() {
        innerShow(PageStatus.EMPTY)
    }

    override fun showContent() {
        innerShow(PageStatus.CONTENT)
    }

    private fun innerShow(status: PageStatus) {
        if (currentState == status) return
        // 如果之前没有缓存对应状态的view
        if (statusView[status] == null) {
            val view = when (status) {
                PageStatus.LOADING -> {
                    inflateView(config.loadingLayout).apply {
                        addView(this, ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT))
                        config.onStatusChange?.onLoadingCreated(this@StatefulPage, this)
                    }
                }
                PageStatus.EMPTY -> {
                    inflateView(config.emptyLayout).apply {
                        addView(this, ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT))
                        config.onStatusChange?.onEmptyCreated(this@StatefulPage, this)
                        setOnClickListener {
                            retryTask?.invoke()
                        }
                    }
                }
                PageStatus.ERROR -> {
                    inflateView(config.loadingLayout).apply {
                        addView(this, ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT))
                        config.onStatusChange?.onErrorCreated(this@StatefulPage, this)
                        setOnClickListener {
                            retryTask?.invoke()
                        }
                    }
                }
                PageStatus.CONTENT -> getChildAt(0)
            }
            view.visibility = View.GONE
            statusView[status] = view
        }

        // 回调显示状态改变
        config.onStatusChange?.onStateChange(this, status, currentState)
        // 之前的状态的view设置为 隐藏
        statusView[currentState]?.visibility = View.GONE
        // 显示当前状态的view
        statusView[status]?.visibility = View.VISIBLE
        // 更新当前状态
        currentState = status
    }

    private fun inflateView(layoutId: Int) = LayoutInflater.from(context).inflate(layoutId, this, false)

    override fun onDetachedFromWindow() {
        statusView.clear()
        super.onDetachedFromWindow()
    }

}